#include <fcntl.h> 
#include <spdlog/sinks/daily_file_sink.h>

#include "db.h"
#include "db_impl.h"

namespace DB_NAME {
DB::DB() {}
DB::~DB() = default;

RC DB::Open(DB *&db_ptr, Options *options) {
  RC ret = RC::SUCCESS;
  if (IS_NULL(db_ptr = new DBImpl(options))) {
    ret = RC::OUT_OF_MEM;
    GLOB_LOG_ERROR("No memory to create a new DB. ret={}", KR(ret));
  } else {
    GLOB_LOG_INFO("Open DB success!.");
  }
  return ret;
}

RC DB::Close() {
  return RC::SUCCESS;
}

DBImpl::DBImpl(Options *options)
 : options_(options), is_inited_(false)
{
}

void DBImpl::init_logger()
{
  log_ = spdlog::daily_logger_mt(options_->db_name, options_->db_name + ".log",
                                 options_->log_opt.daily_hour, options_->log_opt.daily_min);
  log_->set_level(options_->log_opt.level);
  log_->flush_on(options_->log_opt.flush_on);
  log_->set_pattern(options_->log_opt.pattern);
}

RC DBImpl::open_wal_file()
{
  RC ret = RC::SUCCESS;
  if (INITED_TWICE) {
    ret = RC::INIT_TWICE;
    LOG_WARN("DB has been inited! rc={}", KR(ret));
  } else {
    std::string file_name(options_->db_name + ".wal");
    int fd = open(file_name.c_str(), O_CREAT | O_RDWR | O_CLOEXEC, 0644);
    if (fd < 0) {
      ret = OPEN_FAILED;
      LOG_ERROR("DB open wal file failed, rc={}", KR(ret));
    } else if (IS_NULL(wal_ = new WritableFile(fd))) {
      ret = OUT_OF_MEM;
      LOG_ERROR("Not enough memory for WritableFile, rc={}", KR(ret));
    } else if (IS_NULL(writer_ = new wal::Writer(wal_))) {
      ret = OUT_OF_MEM;
      LOG_ERROR("Not enough memory for Writer, rc={}", KR(ret));
    }
  }
  return ret;
}
}